#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""更新管理器模块
自动升级系统的主控制器，整合所有组件并提供统一的接口"""

import threading
import time
from utils import Logger
from utils.auto_update.version_checker import VersionChecker
from utils.auto_update.update_downloader import UpdateDownloader
from utils.auto_update.update_installer import UpdateInstaller
from utils.auto_update.config_manager import UpdateConfigManager
from utils.auto_update.silent_updater import SilentUpdater
from utils.auto_update.delta_updater import DeltaUpdater

class UpdateManager:
    """更新管理器
    自动升级系统的主控制器，负责协调各个组件的工作"""
    
    def __init__(self):
        """初始化更新管理器"""
        self.config_manager = UpdateConfigManager()
        self.version_checker = VersionChecker()
        self.update_downloader = UpdateDownloader()
        self.update_installer = UpdateInstaller()
        self.silent_updater = SilentUpdater()
        self.delta_updater = DeltaUpdater()
        
        self.update_info = None
        self.is_auto_update_enabled = self.config_manager.get_config("auto_update_enabled", True)
        self.is_silent_update_enabled = self.config_manager.get_config("silent_update_enabled", False)
        self.is_delta_update_enabled = self.config_manager.get_config("delta_update_enabled", True)
        
        self._update_lock = threading.Lock()
        self._background_thread = None
        
        Logger.log_info("更新管理器初始化完成")
        Logger.log_info(f"自动更新功能: {'已启用' if self.is_auto_update_enabled else '已禁用'}")
    
    def start(self):
        """启动自动更新系统"""
        Logger.log_info("启动自动更新系统...")
        
        # 检查是否启用了自动更新
        if not self.is_auto_update_enabled:
            Logger.log_info("自动更新功能已禁用，跳过启动")
            return False
        
        try:
            # 检查是否需要在启动时进行更新检查
            check_on_startup = self.config_manager.get_config("update_during_startup", True)
            
            if check_on_startup:
                # 在后台启动更新检查
                self._start_background_update_check()
            
            # 启动定期更新检查
            check_interval = self.config_manager.get_config("check_interval", 3600)
            self.version_checker.start_periodic_check(check_interval)
            
            # 如果启用了静默更新，启动静默更新系统
            if self.is_silent_update_enabled:
                Logger.log_info("启动静默更新系统")
                self.silent_updater.start_silent_updates(self)
            
            # 配置差分更新
            if self.is_delta_update_enabled:
                Logger.log_info("启用差分更新功能")
                # 设置差分更新配置
                self.delta_updater.configure_delta_options(
                    block_size=self.config_manager.get_config("delta_block_size", 4096),
                    temp_dir=self.config_manager.get_config("delta_temp_dir", None)
                )
            
            Logger.log_info("自动更新系统启动成功")
            Logger.log_info(f"静默更新: {'已启用' if self.is_silent_update_enabled else '已禁用'}")
            Logger.log_info(f"差分更新: {'已启用' if self.is_delta_update_enabled else '已禁用'}")
            return True
        except Exception as e:
            Logger.log_error(f"启动自动更新系统失败: {str(e)}")
            return False
    
    def _start_background_update_check(self):
        """在后台线程中启动更新检查"""
        def background_check():
            try:
                Logger.log_info("在后台开始更新检查...")
                update_info = self.version_checker.check_for_updates()
                
                if update_info:
                    self.update_info = update_info
                    Logger.log_info(f"发现新版本: {update_info['version']}")
                    
                    # 如果是强制更新，立即下载并安装
                    if update_info.get("is_mandatory", False):
                        Logger.log_warning("发现强制更新，将自动下载并安装")
                        self._auto_download_and_install(update_info)
                    # 否则，根据配置决定是自动下载还是提示用户
                    else:
                        prompt_before_install = self.config_manager.get_config("prompt_before_install", True)
                        if prompt_before_install:
                            Logger.log_info("请用户确认是否下载并安装更新")
                            # 实际应用中，这里应该显示一个对话框让用户确认
                            # 这里简化处理，默认自动下载
                            self._auto_download_and_install(update_info)
                        else:
                            Logger.log_info("自动下载并安装更新")
                            self._auto_download_and_install(update_info)
            except Exception as e:
                Logger.log_error(f"后台更新检查失败: {str(e)}")
        
        # 创建并启动后台线程
        self._background_thread = threading.Thread(target=background_check, daemon=True)
        self._background_thread.start()
    
    def _auto_download_and_install(self, update_info):
        """自动下载并安装更新
        
        Args:
            update_info: 更新信息字典
        """
        try:
            # 下载更新包
            Logger.log_info(f"开始自动下载更新包: {update_info['download_url']}")
            
            # 定义下载进度回调
            def progress_callback(progress, total_size, downloaded_size):
                Logger.log_info(f"下载进度: {progress}% ({downloaded_size/1024/1024:.2f}MB / {total_size/1024/1024:.2f}MB)")
            
            package_path = None
            
            # 尝试使用差分更新
            if self.is_delta_update_enabled and update_info.get('delta_available', False):
                Logger.log_info("尝试使用差分更新")
                try:
                    # 获取当前安装的应用程序文件
                    current_app_path = self.config_manager.get_config("application_path", os.path.dirname(os.path.abspath(__file__)))
                    
                    # 检查差分文件是否可用
                    if update_info.get('delta_url'):
                        Logger.log_info(f"下载差分更新包: {update_info['delta_url']}")
                        delta_path = self.update_downloader.download_update(
                            update_info['delta_url'],
                            progress_callback
                        )
                        
                        if delta_path:
                            Logger.log_info("差分更新包下载成功，准备应用补丁")
                            
                            # 应用差分补丁
                            package_path = self.delta_updater.apply_delta(
                                current_app_path,
                                delta_path
                            )
                except Exception as delta_error:
                    Logger.log_warning(f"差分更新失败: {str(delta_error)}")
                    Logger.log_info("回退到完整更新包下载")
            
            # 如果差分更新失败或不适用，则下载完整更新包
            if not package_path:
                # 下载更新包
                package_path = self.update_downloader.download_update(
                    update_info['download_url'],
                    progress_callback
                )
            
            if package_path:
                Logger.log_info("更新包下载成功，准备安装")
                
                # 安装更新
                success = self.update_installer.install_update(package_path)
                
                if success:
                    Logger.log_info("更新安装成功")
                else:
                    Logger.log_error("更新安装失败")
            else:
                Logger.log_error("更新包下载失败")
        except Exception as e:
            Logger.log_error(f"自动下载并安装更新失败: {str(e)}")
    
    def manual_check_for_updates(self):
        """手动检查更新
        
        Returns:
            dict: 更新信息字典，如果没有更新则返回None
        """
        Logger.log_info("执行手动更新检查...")
        
        with self._update_lock:
            update_info = self.version_checker.check_for_updates()
            if update_info:
                self.update_info = update_info
                Logger.log_info(f"发现新版本: {update_info['version']}")
            else:
                Logger.log_info("当前已是最新版本")
            
            return update_info
    
    def manual_download_update(self, update_info=None, callback=None):
        """手动下载更新
        
        Args:
            update_info: 更新信息字典，如果为None则使用上次检查的结果
            callback: 下载进度回调函数
            
        Returns:
            str: 下载的文件路径，如果下载失败则返回None
        """
        if not update_info:
            update_info = self.update_info
            
        if not update_info:
            Logger.log_error("没有可用的更新信息")
            return None
        
        Logger.log_info(f"执行手动下载更新: {update_info['version']}")
        
        with self._update_lock:
            return self.update_downloader.download_update(
                update_info['download_url'],
                callback
            )
    
    def manual_install_update(self, package_path=None, restart_application=True):
        """手动安装更新
        
        Args:
            package_path: 更新包文件路径，如果为None则尝试查找最近下载的更新包
            restart_application: 安装完成后是否重启应用程序
            
        Returns:
            bool: 是否安装成功
        """
        if not package_path:
            Logger.log_error("未指定更新包路径")
            return False
        
        Logger.log_info(f"执行手动安装更新: {package_path}")
        
        with self._update_lock:
            return self.update_installer.install_update(package_path, restart_application)
    
    def get_current_version(self):
        """获取当前应用程序版本
        
        Returns:
            str: 当前版本号
        """
        return self.version_checker.current_version
    
    def get_update_info(self):
        """获取最新的更新信息
        
        Returns:
            dict: 更新信息字典，如果没有可用的更新信息则返回None
        """
        return self.update_info
    
    def is_update_available(self):
        """检查是否有可用更新
        
        Returns:
            bool: 是否有可用更新
        """
        return self.update_info is not None
    
    def enable_auto_update(self):
        """启用自动更新功能
        
        Returns:
            bool: 是否启用成功
        """
        if self.config_manager.set_config("auto_update_enabled", True):
            self.is_auto_update_enabled = True
            Logger.log_info("已启用自动更新功能")
            return True
        else:
            Logger.log_error("启用自动更新功能失败")
            return False
    
    def disable_auto_update(self):
        """禁用自动更新功能
        
        Returns:
            bool: 是否禁用成功
        """
        if self.config_manager.set_config("auto_update_enabled", False):
            self.is_auto_update_enabled = False
            Logger.log_info("已禁用自动更新功能")
            return True
        else:
            Logger.log_error("禁用自动更新功能失败")
            return False
    
    def cleanup(self):
        """清理资源"""
        Logger.log_info("清理自动更新系统资源...")
        
        # 清理旧的下载文件
        keep_downloads = self.config_manager.get_config("keep_downloads", False)
        self.update_downloader.cleanup_downloads(keep_latest=keep_downloads)
        
        # 清理静默更新资源
        if self.is_silent_update_enabled:
            Logger.log_info("清理静默更新系统资源")
            self.silent_updater.stop_silent_updates()
        
        # 清理差分更新临时文件
        if self.is_delta_update_enabled:
            Logger.log_info("清理差分更新临时文件")
            self.delta_updater.cleanup()
        
        Logger.log_info("自动更新系统资源清理完成")

# 示例用法
if __name__ == "__main__":
    update_manager = UpdateManager()
    
    # 启动自动更新系统
    update_manager.start()
    
    try:
        # 手动检查更新
        print("手动检查更新...")
        update_info = update_manager.manual_check_for_updates()
        
        if update_info:
            print(f"发现新版本: {update_info['version']}")
            print(f"更新日志: {', '.join(update_info['changelog'])}")
            
            # 实际应用中，这里应该显示一个对话框让用户确认是否下载并安装
            print("模拟用户确认下载并安装更新")
            
            # 定义下载进度回调
            def progress_callback(progress, total_size, downloaded_size):
                print(f"下载进度: {progress}% ({downloaded_size/1024/1024:.2f}MB / {total_size/1024/1024:.2f}MB)")
            
            # 下载更新包
            package_path = update_manager.manual_download_update(update_info, progress_callback)
            
            if package_path:
                print(f"更新包下载成功: {package_path}")
                
                # 安装更新（不重启应用程序）
                success = update_manager.manual_install_update(package_path, restart_application=False)
                
                if success:
                    print("更新安装成功")
                else:
                    print("更新安装失败")
            else:
                print("更新包下载失败")
        else:
            print("当前已是最新版本")
    except KeyboardInterrupt:
        print("用户中断操作")
    finally:
        # 清理资源
        update_manager.cleanup()